package fr.umlv.escapeir.game;

import java.awt.Image;

import org.jbox2d.callbacks.ContactImpulse;
import org.jbox2d.collision.Manifold;
import org.jbox2d.collision.shapes.PolygonShape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.BodyType;
import org.jbox2d.dynamics.Fixture;
import org.jbox2d.dynamics.FixtureDef;
import org.jbox2d.dynamics.contacts.Contact;

import fr.umlv.escapeir.GameWorld;
import fr.umlv.escapeir.gesture.Direction;
import fr.umlv.escapeir.painters.AnimatedWorldPainter;
import fr.umlv.escapeir.painters.ExplosionPainter;
import fr.umlv.escapeir.painters.WorldGraphics2D;

public class PolygonShip implements WorldActor {

	private final BodyDef bdef;
	private final GameWorld world;
	private final FixtureDef fdef;

	private Body body;
	private AnimatedWorldPainter painter;
	private Behavior behavior;

	private PolygonShip (GameWorld gameWorld, float x, float y, float angle, PolygonShape shape, final Image image, final Vec2 imageTopLeft, final Vec2 imageBottomRight, int groupIndex) {
		bdef = new BodyDef();
		bdef.type = BodyType.DYNAMIC;
		bdef.position.set(x, y);
		bdef.angle = angle;

		world = gameWorld;
		
		fdef = new FixtureDef();
		fdef.restitution = 0;
		fdef.density = 0;
		fdef.shape = shape;
		
		painter = new AnimatedWorldPainter() {
			final Image img = image;
			final Vec2 topLeft = imageTopLeft;
			final Vec2 bottomRight = imageBottomRight;

			public void render(WorldGraphics2D painter) {
				painter.save();
				painter.translateFromWorld(body.getPosition());
				painter.rotate(body.getAngle());
				painter.drawRectWithImage(topLeft, bottomRight, img);
				painter.restore();
			}
		};

		behavior = Behaviors.Inertia;
	}

	protected AnimatedWorldPainter getPainter () {
		return painter;
	}
	protected Behavior getBehavior () {
		return behavior;
	}

	@Override
	public void render(WorldGraphics2D painter) {
		getPainter().render(painter);
	}

	@Override
	public void apply() {
		getBehavior().apply();
		getPainter().apply();
	}
	
	public static PolygonShip createInWorld(GameWorld world, float x, float y, float angle, Direction dir, int dirValue, PolygonShape shape, final Image image, final Vec2 imageTopLeft, final Vec2 imageBottomRight, int groupIndex) {
		PolygonShip act = new PolygonShip(world, x, y, angle, shape, image, imageTopLeft, imageBottomRight, groupIndex);
		act.body = world.addActor(act, act.bdef);
		Fixture f = act.body.createFixture(act.fdef);
		f.getFilterData().groupIndex = -2;
		act.body.m_userData = act;
		act.behavior = Behaviors.createLinearMove(act.body, dir, dirValue);
		return act;
	}

	@Override
	public void beginContact(Contact contact) {
		if (!contact.isEnabled()) return;
		if (!contact.isTouching()) return;

		Body wall = contact.getFixtureA().getBody();
		wall = (wall == body ? contact.getFixtureB().getBody() : wall);
		if (world.isWall(wall)) return;

		painter = new ExplosionPainter(body, 2, 15);
		body.m_userData = null;
		world.destroyActor(this, body);

	}

	@Override
	public void endContact(Contact contact) {}

	@Override
	public void preSolve(Contact contact, Manifold oldManifold) {}

	@Override
	public void postSolve(Contact contact, ContactImpulse impulse) {}

}